package com.sec.android.app.myfiles.util;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
import android.net.Uri;

import com.samsung.android.sdk.slinkcloud.CloudGatewayMediaStore;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.cloud.CloudFileRecord;
import com.sec.android.app.myfiles.provider.DbTableInfo;

import java.io.File;

/**
 * Created by yunju.cha on 2016-10-12.
 */
public class FileDetailUtils {
    private static final String TAG = "FileDetailUtils";
    private static final String TYPE_DIRECTORY = "vnd.android.document/directory";

    public static class DirInfo {
        public long size;
        public int fileCnt;
        public int dirCnt;

        public DirInfo() {
            size = 0;
            fileCnt = 0;
            dirCnt = 0;
        }
    }

    public static void getDirInfo(Context context, FileRecord record, DirInfo dirInfo, boolean needRecursive) {
        boolean isShowHidden = PreferenceUtils.getShowHiddenFiles(context);

        if (record != null) {
            if (record.getStorageType() == FileRecord.StorageType.Local || record.getStorageType() == FileRecord.StorageType.FolderTree || record.getStorageType() == FileRecord.StorageType.Shortcut) {
                File file = SemFwWrapper.file(record.getFullPath());
                getLocalDirInfo(file, dirInfo, isShowHidden, needRecursive);
            } else if (record.getStorageType() == FileRecord.StorageType.Category) {
                dirInfo.size += record.getSize();
                dirInfo.fileCnt += record.getItemCount(isShowHidden);
            } else if (record.getStorageType() == FileRecord.StorageType.Recent) {
                File file = SemFwWrapper.file(record.getFullPath());
                getLocalDirInfo(file, dirInfo, isShowHidden, false);
            } else if (record.getStorageType() == FileRecord.StorageType.Downloads) {
                dirInfo.fileCnt++;
                dirInfo.size += record.getSize();
            } else if (record.getStorageType() == FileRecord.StorageType.Cloud) {
                if (record.isRoot()) {
                    getCloudRootInfo(context, record, dirInfo);
                } else {
                    Uri cloudUri = CloudGatewayMediaStore.FileBrowser.FileList2.getFileListUri(((CloudFileRecord) record).getDeviceId(),
                            ((CloudFileRecord) record).getParentId());
                    if (cloudUri != null) {
                        String selection = CloudGatewayMediaStore.FileBrowser.FileBrowserColumns.FILE_ID + "=?"; // "document_id =?";
                        String[] selectionArgs = new String[]{
                                ((CloudFileRecord) record).getFileId()};
                        try (Cursor cursor = context.getContentResolver().query(cloudUri, null, selection, selectionArgs, null)) {
                            if (cursor != null && cursor.moveToFirst()) {
                                int childDirCnt = cursor.getInt(cursor.getColumnIndex(CloudGatewayMediaStore.Files.FileColumns.DESCENDANTS_DIR_CNT));
                                int childCnt = cursor.getInt(cursor.getColumnIndex(CloudGatewayMediaStore.Files.FileColumns.DESCENDANTS_CNT));

                                dirInfo.dirCnt += childDirCnt;
                                dirInfo.fileCnt += (childCnt - childDirCnt);
                                dirInfo.size += record.getSize();
                            }
                        }
                    }
                }
            }
        }
    }

    private static void getLocalDirInfo(File file, DirInfo dirInfo, boolean isShowHidden, boolean needRecursive) {
        if (file == null || !file.exists()) {
            return;
        }

        if (file.isDirectory()) {
            File[] fileList = file.listFiles();
            if (fileList != null) {
                for (File content : fileList) {
                    if (isShowHidden || !content.isHidden()) {
                        if (content.isDirectory()) {
                            if (needRecursive) {
                                getLocalDirInfo(content, dirInfo, isShowHidden, needRecursive);
                            }
                            dirInfo.dirCnt++;
                        } else {
                            dirInfo.size += content.length();
                            dirInfo.fileCnt++;
                        }
                    }
                }
            }
        } else {
            dirInfo.fileCnt++;
            dirInfo.size += file.length();
        }
    }

    private static void getCloudRootInfo(Context context, FileRecord record, DirInfo dirInfo) {
        Uri cloudUri = CloudGatewayMediaStore.FileBrowser.FileList2.getFileListUri(((CloudFileRecord) record).getDeviceId(),
                ((CloudFileRecord) record).getParentId());
        if (cloudUri != null) {
            String selection = ((CloudFileRecord) record).getParentId();
            String[] selectionArgs = new String[]{
                    ((CloudFileRecord) record).getFileId()};
            try (Cursor cursor = context.getContentResolver().query(cloudUri, null, selection, selectionArgs, null)) {
                if (cursor != null && cursor.moveToFirst()) {
                    do {
                        if (TYPE_DIRECTORY.equals(cursor.getString(cursor.getColumnIndex(CloudGatewayMediaStore.Files.FileColumns.MIME_TYPE)))) {
                            dirInfo.dirCnt++;
                        } else {
                            dirInfo.fileCnt++;
                        }
                    } while (cursor.moveToNext());
                }
            }
        }
    }

    public static void updateImageDetailInfo(Context context, DbTableInfo tableInfo, FileRecord record) {
        Long time = System.currentTimeMillis();
        int[] resolutionInfo = getImageResolution(record);
        String resolution = UiUtils.makeResolutionString(context, resolutionInfo);
        record.setDetailMediaInfo(new Object[]{resolution});

        ContentValues value = new ContentValues();
        value.put(tableInfo.getColumnName(DbTableInfo.COLUMN_ID.WIDTH), resolutionInfo[0]); // width
        value.put(tableInfo.getColumnName(DbTableInfo.COLUMN_ID.HEIGHT), resolutionInfo[1]);    // height

        updateDbRecord(context, tableInfo, value, record);

        time = System.currentTimeMillis() - time;
        Log.d(TAG, "updateImageDetailInfo time " + time);
    }

    public static int[] getImageResolution(FileRecord record) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        BitmapFactory.decodeFile(record.getFullPath(), options);
        int width = options.outWidth;
        int height = options.outHeight;
        return new int[]{width, height};
    }

    public static void updateAudioDetailInfo(Context context, DbTableInfo tableInfo, FileRecord record) {
        final String unknown = "unknown";
        Long time = System.currentTimeMillis();
        String artist = null;
        String album = null;
        MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
        try {
            String path = record.getFullPath();
            File f = null;
            if (path != null)
                f = SemFwWrapper.file(path);
            if (f != null && f.exists() && f.length() > 0) {
                mediaMetadataRetriever.setDataSource(path);
                artist = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
                album = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
            }
        } catch (RuntimeException e) {
            Log.e(TAG, "RuntimeException:" + e.toString());
        } finally {
            mediaMetadataRetriever.release();
        }

        if (artist == null) artist = unknown;
        if (album == null) album = unknown;

        record.setDetailMediaInfo(new Object[]{artist, album});

        ContentValues value = new ContentValues();
        value.put(tableInfo.getColumnName(DbTableInfo.COLUMN_ID.ARTIST), artist);
        value.put(tableInfo.getColumnName(DbTableInfo.COLUMN_ID.ALBUM), album);

        updateDbRecord(context, tableInfo, value, record);
        time = System.currentTimeMillis() - time;
        Log.d(TAG, "updateAudioDetailInfo time " + time);
    }

    public static void updateDbRecord(Context context, DbTableInfo tableInfo, ContentValues value, FileRecord record) {
        String pathCol = tableInfo.getColumnName(DbTableInfo.COLUMN_ID.PATH);
        String nameCol = tableInfo.getColumnName(DbTableInfo.COLUMN_ID.NAME);

        try {
            context.getContentResolver().update(Uri.parse(tableInfo.getUri()),
                    value,
                    String.format("%s=? AND %s=?", pathCol, nameCol),
                    new String[]{record.getPath(), record.getName()});
        } catch (SQLiteException e) {
            Log.e(TAG, "SQLiteException:" + e.toString());
        }
    }

    public static void updateVideoDetailInfo(Context context, DbTableInfo tableInfo, FileRecord record) {
        Long time = System.currentTimeMillis();

        Object detailInfo[] = record.getDetailMediaInfo();
        boolean bUpdate = false;

        if (detailInfo == null) {
            detailInfo = new Object[2];
            detailInfo[0] = getMediaDuration(record);
            bUpdate = true;
        }

        if (bUpdate) {
            record.setDetailMediaInfo(detailInfo);

            ContentValues value = new ContentValues();
            value.put(tableInfo.getColumnName(DbTableInfo.COLUMN_ID.DURATION), (Long) detailInfo[0]);

            updateDbRecord(context, tableInfo, value, record);

            time = System.currentTimeMillis() - time;
            Log.d(TAG, "updateVideoDetailInfo time " + time);
        }
    }

    public static long getMediaDuration(FileRecord record) {
        String strDuration = null;
        MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
        try {
            String path = record.getFullPath();
            File f = null;
            if (path != null)
                f = SemFwWrapper.file(path);
            if (f != null && f.exists() && f.length() > 0) {
                mediaMetadataRetriever.setDataSource(path);
                strDuration = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception:" + e.toString());
        } finally {
            mediaMetadataRetriever.release();
        }

        long duration = 0;
        if (strDuration != null) {
            duration = Long.parseLong(strDuration);
        }
        return duration;
    }
}
